﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace Commands
{

    public class UndoService : IUndoCommands
    {
        //Constructor
        public UndoService()
        {
            UndoCommands = new Stack<IUMLCommand>();
            UndoTitles = new ObservableCollection<string>();
            RedoCommands = new Stack<IUMLCommand>();
            RedoTitles = new ObservableCollection<string>();
        }


        //get undo history
        public Stack<IUMLCommand> UndoCommands { get; protected set; }

        //get redo history
        public Stack<IUMLCommand> RedoCommands { get; protected set; }

        //get undo titles
        public ObservableCollection<string> UndoTitles { get; protected set; }

        //get redo titles
        public ObservableCollection<string> RedoTitles { get; protected set; }

        //return if undo is possible
        public bool CanUndo { get { return UndoCommands.Count > 0; } }

        //return if redo is possible
        public bool CanRedo { get { return RedoCommands.Count > 0; } }

        //Execute command and add to undo stack
        public void Execute(IUMLCommand command)
        {
            if (command == null) return;
            // Execute command
            command.Execute();
            // Push command to undo history
            if (command is IUMLCommand)
            {
                UndoCommands.Push(command);
                UndoTitles.Insert(0, command.Title);
                // Clear the redo history upon adding new undo entry.
                RedoCommands.Clear();
                RedoTitles.Clear();
            }
        }

        //Undo last command
        public void Undo()
        {
            if (CanUndo)
            {
                IUMLCommand command = UndoCommands.Pop();
                command.Undo();
                UndoTitles.RemoveAt(0);
                RedoCommands.Push(command);
                RedoTitles.Insert(0, command.Title);
            }
        }

        //Redo last undo
        public void Redo()
        {
            if (CanRedo)
            {
                IUMLCommand command = RedoCommands.Pop();
                RedoTitles.RemoveAt(0);
                //Execute(command);
                if (command != null)
                {
                    command.Execute();

                    if (command is IUMLCommand)
                    {
                        UndoCommands.Push(command);
                        UndoTitles.Insert(0, command.Title);
                    }
                }
            }
        }

        //Clear history
        public void ClearUndoHistory()
        {
            UndoCommands.Clear();
            UndoTitles.Clear();
        }

        //Clear redo history
        public void ClearRedoHistory()
        {
            RedoCommands.Clear();
            RedoTitles.Clear();
        }

        //Clear undo history
        public void ClearHistory()
        {
            ClearRedoHistory();
            ClearUndoHistory();
        }

    }

}
